/*------------------------------------------------------------------------------
 * Copyright 2012 NCR Corporation
 *------------------------------------------------------------------------------
 * All revision information is updated automatically from source code control
 * change records - please do not manually edit.
 *------------------------------------------------------------------------------
 *
 * $LastChangedRevision:: 2026                                     $
 * $LastChangedBy:: rb250096                                       $
 * $LastChangedDate:: 2012-04-07 18:34:30 -0400 (Sat, 07 Apr 2012) $
 */

package com.ncr.nep.dashboardcore.rest.client;

import com.google.gwt.http.client.RequestCallback;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;

/**
 * {@link RESTService} extension that provides a reusable service for CRUD
 * (Create, Read, Update, and Delete) resources that follow a common REST
 * resource pattern.  Specifically, this service can be used when the following
 * URL patterns are met for the CRUD operations:
 *
 * <ul>
 *     <li><em>/some/url (GET)</em> - Read all</li>
 *     <li><em>/some/url/{identifier} (GET)</em> - Read single</li>
 *     <li><em>/some/url (POST)</em> - Create</li>
 *     <li><em>/some/url/{identifier} (PUT)</em> - Update</li>
 *     <li><em>/some/url/{identifier} (DELETE)</em> - Delete</li>
 * </ul>
 *
 * @author rb250096
 * @version $Revision: 2026 $
 */
public class CRUDService extends RESTService {

    //--------------------------------------------------------------------------
    //
    //  Constructors
    //
    //--------------------------------------------------------------------------

    /**
     * Constructor.
     *
     * @param baseURL The base URL of the service.
     */
    public CRUDService(String baseURL) {
        super(baseURL);
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Reads all objects from the underlying REST resource.
     *
     * @param callback Callback invoked when the request completes.
     */
    public void readAll(RequestCallback callback) {
        this.get(this.newRequest(), callback);
    }

    /**
     * Reads a single object from the underlying REST resource.
     *
     * @param id The unique identifier of the object to get.
     * @param callback Callback invoked when the request completes.
     */
    public void read(Object id, RequestCallback callback) {
        this.get(id.toString(), this.newRequest(), callback);
    }

    /**
     * Creates a new object and posts it to the REST resource.
     *
     * @param data String containing data to send in body of create request.
     * @param callback Callback invoked when the request completes.
     */
    public void create(String data, RequestCallback callback) {
        this.post(this.newRequest().contentType(MIMEType.APPLICATION_JSON)
                    .accept(MIMEType.TEXT_PLAIN)
                    .data(data),
                callback);
    }

    /**
     * Creates a new object and posts it to the REST resource.
     *
     * @param bean {@link AutoBean} that will be converted to JSON and sent
     *             in the body of the message to the server.
     * @param callback Callback invoked when the request completes.
     */
    public void create(AutoBean<?> bean, RequestCallback callback) {
        String data = AutoBeanCodex.encode(bean).getPayload();
        this.create(data, callback);
    }

    /**
     * Updates an existing resource.
     *
     * @param data String containing data to send in body of update request
     *             representing the updated entity.
     * @param id The ID of the object to update.
     * @param callback Callback invoked when the request completes.
     */
    public void update(String data, Object id, RequestCallback callback) {
        this.put(id.toString(),
                this.newRequest().contentType(MIMEType.APPLICATION_JSON)
                    .accept(MIMEType.TEXT_PLAIN)
                    .data(data),
                callback);
    }

    /**
     * Updates an existing resource.
     *
     * @param bean {@link AutoBean} that will be converted to JSON and sent
     *             in the body of the message to the server.
     * @param id The ID of the object to update.
     * @param callback Callback invoked when the request completes.
     */
    public void update(AutoBean<?> bean, Object id, RequestCallback callback) {
        String data = AutoBeanCodex.encode(bean).getPayload();
        this.update(data, id, callback);
    }

    /**
     * Deletes the object/resource with the specified ID.
     *
     * @param id The unique identifier of the object to delete on the server.
     * @param callback Callback invoked when the request completes.
     */
    public void delete(Object id, RequestCallback callback) {
        this.delete(id.toString(), new HTTPRequest(), callback);
    }

    /**
     * Returns a new {@link HTTPRequest} with the correct properties set.
     *
     * @return The new HTTPRequest.
     */
    protected HTTPRequest newRequest() {
        return new HTTPRequest().accept(MIMEType.APPLICATION_JSON);
    }
}
